﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Cofe.Core.Utils;
using Cofe.Core.Property;

namespace Cofe.Core
{
    public class StreamContainer : IDisposable
    {

        #region Constructor

        public StreamContainer()
        {
            _stream = new MemoryStream();
        }


#if NETFX_CORE
        public static StreamContainer FromInputStream(Windows.Storage.Streams.IInputStream stream, string path)
        {
            if (stream == null)
                throw new ArgumentException("stream");
            return new StreamContainer() { _inputStream = stream, Path = path  };
        }

        public static StreamContainer FromOutputStream(Windows.Storage.Streams.IOutputStream stream, string path)
        {
            if (stream == null)
                throw new ArgumentException("stream");
            return new StreamContainer() { _outputStream = stream, Path = path  };
        }

        public static StreamContainer FromRandomAccessStream(Windows.Storage.Streams.IRandomAccessStream stream, string path)
        {
            if (stream == null)
                throw new ArgumentException("stream");
            return new StreamContainer() { _randomAccessStream = stream, Path = path  };
        }

#endif


        public static StreamContainer FromIOStream(System.IO.Stream stream, string path)
        {
            if (stream == null)
                throw new ArgumentException("stream");
            return new StreamContainer() { _stream = stream, Path = path };
        }

        public static StreamContainer FromByte(byte[] bytes)
        {
            var ms = new MemoryStream();
            var bw = new BinaryWriter(ms);
            bw.Write(bytes);
            bw.Seek(0, SeekOrigin.Begin);

            return new StreamContainer() { _stream = ms };
        }

        #endregion

        #region Methods      

        private void setPath(string path)
        {
            if (!(String.IsNullOrEmpty(path)))
            {
                _path = path.Replace('/', '\\');
                _type = PathFE.GetExtension(_path).ToLower().Trim('.');
            }
        }

#if NETFX_CORE

        private Windows.Storage.Streams.IInputStream getInputStream()
        {
            if (_inputStream != null)
                return _inputStream;
            if (_stream != null)
                return _stream.AsInputStream();
            throw new Exception("StreamContainer: Cannot create input stream.");
        }

        private Windows.Storage.Streams.IOutputStream getOutputStream()
        {
            if (_outputStream != null)
                return _outputStream;
            if (_stream != null)
                return _stream.AsOutputStream();
            throw new Exception("StreamContainer: Cannot create input stream.");
        }

#endif

#if NETFX_CORE
        public void Dispose()
        {
            if (_stream != null)
            {
                _stream.Dispose();
                _stream = null;
            }

            if (_inputStream != null)
            {
                _inputStream.Dispose();                
                _inputStream = null;
            }
            if (_outputStream != null)
            {
                _outputStream.Dispose();
                _outputStream = null;
            }
            if (_randomAccessStream != null)
            {
                _randomAccessStream.Dispose();
                _randomAccessStream = null;
            }

         
        }
#else
        public void Dispose()
        {
            if (_stream != null)
                _stream.Dispose();
        }
#endif

        ~StreamContainer()
        {
            Dispose();
        }

        public byte[] GetByte()
        {
            return Stream.ToByteArray();
        }

        protected virtual Stream getStream()
        {
            if (_stream != null)
                return _stream;
#if NETFX_CORE
            if (_inputStream != null)
                _stream = _inputStream.AsStreamForRead();
            if (_outputStream != null)
                _stream = _outputStream.AsStreamForWrite();
            if (_randomAccessStream != null)
                _stream = _randomAccessStream.AsStream();

            if (_stream != null)
                return _stream;
#endif          

            throw new Exception("StreamContainer: Cannot create stream.");
        }

        
        #endregion

        #region Data

#if NETFX_CORE
        private Windows.Storage.Streams.IInputStream _inputStream;
        private Windows.Storage.Streams.IOutputStream _outputStream;
        private Windows.Storage.Streams.IRandomAccessStream _randomAccessStream;     
#endif
        private System.IO.Stream _stream;
        private string _type, _path;


        #endregion

        #region Public Properties
#if NETFX_CORE
        public Windows.Storage.Streams.IInputStream InputStream { get { return getInputStream(); } }
        public Windows.Storage.Streams.IOutputStream OutputStream { get { return getOutputStream(); } }
#endif
        public System.IO.Stream Stream { get { return getStream(); } }
        public string Type { get { return _type; } }
        public string Path { get { return _path; } private set { setPath(value); } }

        #endregion


      
    }
}
